package com.bilibili.server.service;


import cn.hutool.core.util.PageUtil;
import com.bilibili.autoconfig.template.OssTemplate;
import com.bilibili.commons.Constants;
import com.bilibili.commons.exception.TanHuaException;
import com.bilibili.dubbo.api.db.UserInfoApi;
import com.bilibili.dubbo.api.mongo.VideoApi;
import com.bilibili.model.db.UserInfo;
import com.bilibili.model.mongo.Video;
import com.bilibili.model.vo.PageResult;
import com.bilibili.model.vo.VideoVo;
import com.bilibili.server.interceptor.UserHolder;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author HuangRongFu
 * 2021/11/26 星期五4:53 下午
 */

@Service
@Slf4j
public class SmallVideoService {

    @Autowired
    private FastFileStorageClient client;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private FdfsWebServer fdfsWebServer;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserFreezeService userFreezeService;

    @Autowired
    private MqMessageService mqMessageService;

    @DubboReference
    private VideoApi videoApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    /**
     * 发布小视频
     *
     * @param videoThumbnail
     * @param videoFile
     * @Return: null
     */
    @CacheEvict(value="videos",allEntries = true)
    public void uploadVideo(MultipartFile videoThumbnail, MultipartFile videoFile) {

        userFreezeService.checkUserStatus(3, UserHolder.getUser().getMobile());

        try {
            //视频封面上传到oss
            String pirUrl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());

            //视频上传到fastDFS 回去访问的URL
            String filename = videoFile.getOriginalFilename();

            //不加1得到的是mp4 不需要
            String extension = filename.substring(filename.lastIndexOf(".") + 1);
            StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), extension, null);

            String videoUrl = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();

            //构建videos对象
            Video pojo = new Video();
            pojo.setId(new ObjectId());
            pojo.setText("哈哈哈哈");
            pojo.setPicUrl(pirUrl);
            pojo.setVideoUrl(videoUrl);
            pojo.setUserId(UserHolder.getUserId());

            //调用api保存数据
            videoApi.add(pojo);

            mqMessageService.sendLogMessage(UserHolder.getUserId(), "0301", "video", pojo.getId().toHexString());

        } catch (IOException e) {
            log.error("上传小视频失败!", e);
            throw new TanHuaException("上传小视频失败!");
        }
    }

    /**
     * 小视频列表
     *
     * @param page
     * @param pageSize
     * @Return: PageResult
     */
    public PageResult<VideoVo> findPage(Long page, Long pageSize) {

        //先从推荐列表查视频数据
        String key = Constants.VIDEOS_RECOMMEND + UserHolder.getUserId();
        String redisVid = stringRedisTemplate.opsForValue().get(key);

        Long total = 0l;
        int redisPages = 0;
        List<Video> videoList = new ArrayList<>();

        //如果获取到的id字符串不为空
        if (StringUtils.isNotEmpty(redisVid)) {

            //分割字符串得到id数组
            String[] vidArr = redisVid.split(",");

            //算出redis总页数
            total = Long.valueOf(vidArr.length);

            redisPages = PageUtil.totalPage(total.intValue(), pageSize.intValue());

            //分页查询
            if (total > pageSize) {

                List<Long> vidList = Arrays.stream(vidArr).skip(total).
                        limit(pageSize).map(vid -> Long.valueOf(vid)).collect(Collectors.toList());

                videoList = videoApi.findByVids(vidList);
            }
        }

        //如果推荐列表查完了 就去数据库查询数据
        if (CollectionUtils.isEmpty(videoList)) {

            //取数据库按时间降序查询小视频列表
            PageResult<Video> pageResult = videoApi.findPage(page - redisPages, pageSize);

            //总记录数等于 数据库记录数 + 推荐的记录数
            total += pageResult.getCounts();
            videoList = pageResult.getItems();
        }

        //补充作者信息
        List<VideoVo> voList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(videoList)) {

            //所有作者的id集合
            List<Long> userIds = videoList.stream().map(Video::getUserId).collect(Collectors.toList());

            // 批量查询
            java.util.Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIds, null);

            //5. 转成vo
            for (Video video : videoList) {
                VideoVo vo = VideoVo.init(userInfoMap.get(video.getUserId()), video);
                voList.add(vo);
            }
        }

        //6. 返回
        return new PageResult<VideoVo>(page, pageSize, total, voList);
    }
}
